/*
* Copyright (c) 2012-2013 by Justin Jensen <justin@gravitygame.hostingsiteforfree.com>
*
* All rights reserved. No warranty, explicit or implicit, provided.
*
*/

var c;
var ctx;

//var startBodyCount = Math.floor(random(500,600));
var G = 0.1;
var scale = 1; //Scale = world size / screen size

var scnOffset = new Vector(0,0);

var bodies = [];
var scWidth;
var scHeight;
var viewWidth;
var viewHeight;
var infoBarHeight = 0;
var trailLength = 100;

var showTrails = true;
var paused = false;
//var dragging = false;
var panning = true;
var mousePressed = false;
var showMotionVector = false;

//var draggedPlanet = new Body();
var dragStartX, dragStartY, dragEndX, dragEndY;	//world
var lastE; //previous mouse move event while dragging

var mouseX; //screen
var mouseY; //screen
//var newPlanetMass = 200;
//var newPlanetRadius = Math.pow((Math.abs(newPlanetMass) * 3 / (4 * Math.PI)), 0.3333);

var playExtras = true;
var recordEnded = false;
var gameTime = 0;
//in the future, this value will be copied in through PHP
var recordingjson = '[{"type":"bookmark","time":0,"data":[{"mass":121.36264443886466,"x":364.83027837577987,"y":501.1604118601218,"motion":{"x":4.2394718148717425,"y":-3.6959835068890188},"trail":[],"width":6.142050784407001,"bodyColor":"#BBBBBB"},{"mass":30.22637554584071,"x":790.6161963289431,"y":388.39335615246426,"motion":{"x":0.15139531369607803,"y":1.9148779246300585},"trail":[],"width":3.864564326498639,"bodyColor":"#BBBBBB"},{"mass":134.40561398072168,"x":957.4064359640741,"y":523.0727110440325,"motion":{"x":-2.3968789796940033,"y":-9.061947614923213},"trail":[],"width":6.354617064188397,"bodyColor":"#BBBBBB"},{"mass":107.8942996847909,"x":353.9238793765619,"y":616.9035942097289,"motion":{"x":2.815446219313654,"y":-1.6062409185479722},"trail":[],"width":5.905902356241868,"bodyColor":"#BBBBBB"},{"mass":81.16147252637893,"x":1389.2408854106309,"y":375.28404798435054,"motion":{"x":-3.8012681152359558,"y":2.183083573197886},"trail":[],"width":5.371235444790683,"bodyColor":"#BBBBBB"},{"mass":40.182603074004874,"x":1328.397307945557,"y":420.97794669220434,"motion":{"x":-5.894464767163146,"y":-3.3391270422662127},"trail":[],"width":4.2492643531957945,"bodyColor":"#BBBBBB"},{"mass":43.09547691280022,"x":372.7071028851979,"y":451.43055642922116,"motion":{"x":3.0189818169235876,"y":1.5673436960912717},"trail":[],"width":4.34954616650129,"bodyColor":"#BBBBBB"},{"mass":87.40064261853695,"x":1196.6035411297366,"y":620.4601436111038,"motion":{"x":-1.7407538744681865,"y":-3.174611883533614},"trail":[],"width":5.505473632105369,"bodyColor":"#BBBBBB"},{"mass":150.93535722023807,"x":862.212549187707,"y":408.52146784927766,"motion":{"x":2.197792599029353,"y":3.5066406016658305},"trail":[],"width":6.605092410678646,"bodyColor":"#BBBBBB"},{"mass":44.84102702024393,"x":648.7619163794847,"y":621.5716034012034,"motion":{"x":2.266146429821414,"y":-3.289846268129644},"trail":[],"width":4.407489875110266,"bodyColor":"#BBBBBB"},{"mass":52.880617457209155,"x":917.7805410150689,"y":380.5409889341203,"motion":{"x":-3.0871175985256287,"y":-3.793444802418025},"trail":[],"width":4.656531996469499,"bodyColor":"#BBBBBB"},{"mass":106.17057279357687,"x":603.0559504390292,"y":539.3199198735523,"motion":{"x":-1.6327322842554837,"y":-3.6045319526615542},"trail":[],"width":5.874285482590871,"bodyColor":"#BBBBBB"},{"mass":106.76888378127478,"x":1140.6531580673334,"y":590.6295834686904,"motion":{"x":-0.7914988318551975,"y":1.1975238926775646},"trail":[],"width":5.885298317224297,"bodyColor":"#BBBBBB"},{"mass":197.53768999758177,"x":747.0527115984653,"y":675.8049313163248,"motion":{"x":2.1719629537680354,"y":-1.117446066829336},"trail":[],"width":7.224836069509511,"bodyColor":"#BBBBBB"},{"mass":151.3152902519796,"x":619.0529950118242,"y":596.0522040208633,"motion":{"x":2.418168279702686,"y":-3.784930246798681},"trail":[],"width":6.610629304756045,"bodyColor":"#BBBBBB"},{"mass":188.88951259246096,"x":1127.727566979567,"y":601.1903694698293,"motion":{"x":-2.7915256559047017,"y":-2.9247284429949216},"trail":[],"width":7.1178353429846295,"bodyColor":"#BBBBBB"},{"mass":139.84732985077426,"x":414.5246057976593,"y":540.7741269763637,"motion":{"x":2.8575176983222965,"y":-3.1398297361714165},"trail":[],"width":6.439236852857982,"bodyColor":"#BBBBBB"},{"mass":175.10528341913596,"x":1125.2938765918473,"y":403.4733910537418,"motion":{"x":-6.530516148674154,"y":3.3227784785453953},"trail":[],"width":6.94032011450791,"bodyColor":"#BBBBBB"},{"mass":418.1714728428051,"x":1071.111744185412,"y":475.82738285669194,"motion":{"x":-3.133310401065114,"y":2.8324850703841284},"trail":[],"width":9.276524256476513,"bodyColor":"#BBBBBB"},{"mass":216.0255921103526,"x":1368.804273519302,"y":453.7137434134426,"motion":{"x":-3.028068492002294,"y":3.7737454113148887},"trail":[],"width":7.4435214932350275,"bodyColor":"#BBBBBB"},{"mass":616.6258536223322,"x":661.162441600728,"y":576.6731675932015,"motion":{"x":1.742731543227155,"y":0.04016946523802519},"trail":[],"width":10.558497092986771,"bodyColor":"#BBBBBB"},{"mass":381.3804906173609,"x":1424.2603815621035,"y":362.0707726434747,"motion":{"x":-3.702605670927575,"y":3.1157267358603358},"trail":[],"width":8.996107599884857,"bodyColor":"#BBBBBB"},{"mass":639.8870757541154,"x":875.4541720909189,"y":482.53590085205224,"motion":{"x":4.478932994956239,"y":-2.5669612098237846},"trail":[],"width":10.689616011204931,"bodyColor":"#BBBBBB"},{"mass":1515.5589183294214,"x":1081.0674234171665,"y":400.3251610055532,"motion":{"x":-0.2962858215897379,"y":1.2816209129833815},"trail":[],"width":14.248619352900539,"bodyColor":"#BBBBBB"},{"mass":591.0782155650668,"x":725.8693331519937,"y":501.11428170783284,"motion":{"x":2.289312706791824,"y":-2.5015881541043066},"trail":[],"width":10.41063272150288,"bodyColor":"#BBBBBB"},{"mass":283.4181630082894,"x":882.9017422203292,"y":530.2273344102696,"motion":{"x":0.35927296820201154,"y":1.066442743215672},"trail":[],"width":8.148581385966011,"bodyColor":"#BBBBBB"},{"mass":497.8019497601781,"x":378.7215555602199,"y":702.0393986282576,"motion":{"x":-0.016828165128774726,"y":-2.318859355639616},"trail":[],"width":9.83143301878001,"bodyColor":"#BBBBBB"},{"mass":1440.3666240004823,"x":1029.8758176369395,"y":455.25341844357564,"motion":{"x":-0.5220698568959224,"y":3.7213448366195334},"trail":[],"width":14.008993363479892,"bodyColor":"#BBBBBB"},{"mass":375.72240823181346,"x":858.492571888266,"y":430.96900010426293,"motion":{"x":-3.1474285555827497,"y":2.368730540069472},"trail":[],"width":8.951402089739203,"bodyColor":"#BBBBBB"},{"mass":331.3578441401478,"x":1232.0351553236385,"y":314.81858632200647,"motion":{"x":-1.1702734268615391,"y":1.798307695714871},"trail":[],"width":8.58426147328207,"bodyColor":"#BBBBBB"},{"mass":2574.587919484591,"x":390.6515909760004,"y":479.2612408424252,"motion":{"x":2.362900887639543,"y":-1.3644180041232816},"trail":[],"width":17.001089264291732,"bodyColor":"#BBBBBB"},{"mass":1142.0444469039794,"x":333.6705098316477,"y":708.9701640976251,"motion":{"x":2.3099023324520584,"y":-2.058711540444167},"trail":[],"width":12.966226632424897,"bodyColor":"#BBBBBB"},{"mass":759.9685456238221,"x":1123.9187217257,"y":576.1239146857561,"motion":{"x":-0.9679570671999835,"y":-4.411044522047441},"trail":[],"width":11.320276677884722,"bodyColor":"#BBBBBB"},{"mass":2930.0012317886576,"x":757.2230465929787,"y":577.0796940766933,"motion":{"x":1.1483501991931686,"y":-2.7406285952704605},"trail":[],"width":17.749858730765684,"bodyColor":"#BBBBBB"},{"mass":1468.9831294466276,"x":581.7325027614029,"y":521.6214801592305,"motion":{"x":1.9270588552056707,"y":-0.18731752874461216},"trail":[],"width":14.101151037412082,"bodyColor":"#BBBBBB"},{"mass":4367.928428345593,"x":1276.6004745568528,"y":462.270914973152,"motion":{"x":-1.506393884562357,"y":3.175060567353751},"trail":[],"width":20.276439251649904,"bodyColor":"#BBBBBB"},{"mass":1697.9247570752632,"x":1322.793830679698,"y":358.5804695829984,"motion":{"x":-1.6039603733983951,"y":-0.2996883908354277},"trail":[],"width":14.798567524402987,"bodyColor":"#BBBBBB"},{"mass":5860.319457991514,"x":396.4486509035496,"y":356.5795208623148,"motion":{"x":1.4438946408141085,"y":1.9488819173386354},"trail":[],"width":22.36330713854718,"bodyColor":"#BBBBBB"},{"mass":195.3553025291767,"x":908.8174776608198,"y":468.56480223069735,"motion":{"x":-2.367942137402084,"y":1.0900000523551634},"trail":[],"width":7.198133592467826,"bodyColor":"#BBBBBB"},{"mass":231.3194077492226,"x":855.2790526700566,"y":460.678577686985,"motion":{"x":8.037920539801958,"y":2.189135305038093},"trail":[],"width":7.615172503439896,"bodyColor":"#BBBBBB"},{"mass":326.7031093041878,"x":427.21673337693704,"y":445.2166736736362,"motion":{"x":2.3348457228390624,"y":1.6505033499574853},"trail":[],"width":8.543880124551096,"bodyColor":"#BBBBBB"},{"mass":2654.445581197506,"x":858.174960800797,"y":475.4847031794601,"motion":{"x":-0.7007478510739338,"y":2.531228532768838},"trail":[],"width":17.1750629886772,"bodyColor":"#BBBBBB"},{"mass":2203.6662190239877,"x":884.4192837736998,"y":454.95210913409034,"motion":{"x":3.955072090814591,"y":3.345791675859961},"trail":[],"width":16.142037877927834,"bodyColor":"#BBBBBB"},{"mass":7454.8756504997145,"x":1378.7806543596912,"y":562.2668280988484,"motion":{"x":-2.23732230238337,"y":-1.6626396001972619},"trail":[],"width":24.231050835732155,"bodyColor":"#BBBBBB"},{"mass":7266.856818759115,"x":983.4297515840065,"y":533.5111067510418,"motion":{"x":-0.6033748757187191,"y":-2.066521723673553},"trail":[],"width":24.0256244945742,"bodyColor":"#BBBBBB"}]},{"type":"trails","time":0,"data":true},{"type":"motion","time":0,"data":false},{"type":"zoom","time":0,"data":1},{"type":"pan","time":0,"data":{"x":0,"y":0}},{"type":"pan","time":200,"data":{"x":-1,"y":0}},{"type":"pan","time":200,"data":{"x":-4,"y":-1}},{"type":"pan","time":200,"data":{"x":-6,"y":-1}},{"type":"pan","time":205,"data":{"x":-34,"y":-2}},{"type":"pan","time":205,"data":{"x":-35,"y":-2}},{"type":"pan","time":210,"data":{"x":-63,"y":10}},{"type":"pan","time":210,"data":{"x":-66,"y":11}},{"type":"pan","time":210,"data":{"x":-71,"y":13}},{"type":"pan","time":215,"data":{"x":-95,"y":29}},{"type":"pan","time":215,"data":{"x":-97,"y":30}},{"type":"pan","time":220,"data":{"x":-107,"y":53}},{"type":"pan","time":220,"data":{"x":-109,"y":55}},{"type":"pan","time":225,"data":{"x":-112,"y":75}},{"type":"pan","time":225,"data":{"x":-112,"y":77}},{"type":"pan","time":230,"data":{"x":-83,"y":124}},{"type":"pan","time":230,"data":{"x":-78,"y":129}},{"type":"pan","time":235,"data":{"x":-40,"y":157}},{"type":"pan","time":235,"data":{"x":-37,"y":160}},{"type":"pan","time":240,"data":{"x":3,"y":199}},{"type":"pan","time":240,"data":{"x":7,"y":204}},{"type":"pan","time":245,"data":{"x":35,"y":246}},{"type":"pan","time":245,"data":{"x":37,"y":248}},{"type":"pan","time":245,"data":{"x":38,"y":250}},{"type":"pan","time":275,"data":{"x":57,"y":276}},{"type":"pan","time":275,"data":{"x":64,"y":285}},{"type":"pan","time":280,"data":{"x":105,"y":352}},{"type":"pan","time":280,"data":{"x":108,"y":358}},{"type":"pan","time":285,"data":{"x":147,"y":423}},{"type":"pan","time":285,"data":{"x":150,"y":428}},{"type":"pan","time":290,"data":{"x":188,"y":483}},{"type":"pan","time":290,"data":{"x":193,"y":492}},{"type":"pan","time":295,"data":{"x":232,"y":554}},{"type":"pan","time":300,"data":{"x":260,"y":588}},{"type":"pan","time":300,"data":{"x":265,"y":592}},{"type":"pan","time":330,"data":{"x":310,"y":619}},{"type":"pan","time":330,"data":{"x":314,"y":625}},{"type":"pan","time":335,"data":{"x":373,"y":704}},{"type":"pan","time":335,"data":{"x":379,"y":709}},{"type":"pan","time":340,"data":{"x":438,"y":776}},{"type":"pan","time":340,"data":{"x":446,"y":784}},{"type":"pan","time":345,"data":{"x":492,"y":838}},{"type":"pan","time":345,"data":{"x":496,"y":844}},{"type":"pan","time":350,"data":{"x":548,"y":913}},{"type":"pan","time":350,"data":{"x":554,"y":921}},{"type":"pan","time":385,"data":{"x":587,"y":956}},{"type":"pan","time":385,"data":{"x":591,"y":958}},{"type":"pan","time":390,"data":{"x":691,"y":1049}},{"type":"pan","time":390,"data":{"x":704,"y":1062}},{"type":"pan","time":395,"data":{"x":772,"y":1137}},{"type":"pan","time":395,"data":{"x":780,"y":1146}},{"type":"pan","time":400,"data":{"x":840,"y":1214}},{"type":"pan","time":400,"data":{"x":844,"y":1217}},{"type":"pan","time":405,"data":{"x":921,"y":1280}},{"type":"pan","time":405,"data":{"x":929,"y":1286}},{"type":"pan","time":410,"data":{"x":966,"y":1316}},{"type":"pan","time":410,"data":{"x":969,"y":1319}},{"type":"pan","time":450,"data":{"x":1025,"y":1379}},{"type":"pan","time":450,"data":{"x":1030,"y":1385}},{"type":"pan","time":455,"data":{"x":1081,"y":1429}},{"type":"pan","time":455,"data":{"x":1086,"y":1435}},{"type":"pan","time":460,"data":{"x":1139,"y":1484}},{"type":"pan","time":460,"data":{"x":1146,"y":1491}},{"type":"pan","time":465,"data":{"x":1195,"y":1538}},{"type":"pan","time":465,"data":{"x":1200,"y":1544}},{"type":"pan","time":465,"data":{"x":1206,"y":1549}},{"type":"pan","time":470,"data":{"x":1258,"y":1606}},{"type":"pan","time":470,"data":{"x":1264,"y":1614}},{"type":"pan","time":475,"data":{"x":1329,"y":1693}},{"type":"pan","time":475,"data":{"x":1337,"y":1702}},{"type":"pan","time":480,"data":{"x":1396,"y":1779}},{"type":"pan","time":601,"data":{"x":2292.5,"y":2278.5}},{"type":"zoom","time":601,"data":0.5},{"type":"pan","time":610,"data":{"x":4085.5,"y":3275.5}},{"type":"zoom","time":610,"data":0.25},{"type":"pan","time":620,"data":{"x":7671.5,"y":5269.5}},{"type":"zoom","time":620,"data":0.125},{"type":"pan","time":665,"data":{"x":7615.5,"y":5213.5}},{"type":"pan","time":665,"data":{"x":7567.5,"y":5181.5}},{"type":"pan","time":665,"data":{"x":7511.5,"y":5149.5}},{"type":"pan","time":670,"data":{"x":7103.5,"y":4861.5}},{"type":"pan","time":670,"data":{"x":7071.5,"y":4845.5}},{"type":"pan","time":675,"data":{"x":6663.5,"y":4477.5}},{"type":"pan","time":675,"data":{"x":6623.5,"y":4437.5}},{"type":"pan","time":680,"data":{"x":6247.5,"y":4109.5}},{"type":"pan","time":680,"data":{"x":6215.5,"y":4069.5}},{"type":"pan","time":685,"data":{"x":6095.5,"y":3821.5}},{"type":"pan","time":685,"data":{"x":6087.5,"y":3781.5}},{"type":"pan","time":690,"data":{"x":5951.5,"y":3477.5}},{"type":"pan","time":690,"data":{"x":5951.5,"y":3461.5}},{"type":"zoom","time":758,"data":0.25},{"type":"pan","time":758,"data":{"x":2341.5,"y":1427.5}},{"type":"zoom","time":767,"data":0.5},{"type":"pan","time":767,"data":{"x":548.5,"y":430.5}},{"type":"zoom","time":776,"data":1},{"type":"pan","time":776,"data":{"x":-348,"y":-68}},{"type":"pan","time":805,"data":{"x":-338,"y":-64}},{"type":"pan","time":805,"data":{"x":-334,"y":-63}},{"type":"pan","time":810,"data":{"x":-303,"y":-55}},{"type":"pan","time":810,"data":{"x":-300,"y":-55}},{"type":"pan","time":815,"data":{"x":-237,"y":-40}},{"type":"pan","time":815,"data":{"x":-231,"y":-38}},{"type":"pan","time":820,"data":{"x":-155,"y":-10}},{"type":"pan","time":820,"data":{"x":-152,"y":-9}},{"type":"pan","time":825,"data":{"x":-117,"y":-2}},{"type":"pan","time":825,"data":{"x":-110,"y":-1}},{"type":"pan","time":830,"data":{"x":-85,"y":-2}},{"type":"pan","time":830,"data":{"x":-84,"y":-3}},{"type":"pan","time":840,"data":{"x":-55,"y":-8}},{"type":"pan","time":840,"data":{"x":-53,"y":-7}},{"type":"pan","time":840,"data":{"x":-51,"y":-6}},{"type":"pan","time":845,"data":{"x":-46,"y":1}},{"type":"pan","time":850,"data":{"x":-44,"y":7}},{"type":"newPlanet","time":1345,"data":{"mass":200,"x":852,"y":898,"motion":{"x":0,"y":0},"trail":[],"width":7.2547284271623305,"bodyColor":"#BBBBBB"}},{"type":"newPlanet","time":1406,"data":{"mass":200,"x":869,"y":926,"motion":{"x":2.75,"y":0.3333333333333333},"trail":[],"width":7.2547284271623305,"bodyColor":"#BBBBBB"}},{"type":"newPlanet","time":1522,"data":{"mass":200,"x":894,"y":920,"motion":{"x":1.75,"y":-0.25},"trail":[],"width":7.2547284271623305,"bodyColor":"#BBBBBB"}},{"type":"motion","time":1687,"data":true},{"type":"stop","time":2161,"data":true}]';
var recording = JSON.parse(recordingjson);

document.onkeypress = function(e){
	var charCode = (e.which)? e.which : event.keyCode;
	
	//d - 100
	//p - 112
	//r - 114
	//c - 99
	//s - 115
	//up - 38
	//down - 40
	switch(charCode){
		case 112:		//p
			togglePause();
			break;
	}
};

//var saveGame;
//var loadGame;

window.onresize = function(){
	updateCanvasSize();
};

function updateCanvasSize(){
	scWidth = document.documentElement.clientWidth - 110;
	scHeight = document.documentElement.clientHeight - 120;
	document.getElementById('playArea').width = scWidth;
	document.getElementById('playArea').height = scHeight;
	viewWidth = scWidth;
	viewHeight = scHeight - infoBarHeight;
}

window.onload = function(){

	//
	/*document.getElementById('playArea').onmousedown = function(event){
		event.preventDefault();
	};*/
	
	//scWidth = 1000;
	//scHeight = 800;
	updateCanvasSize();
	
	//viewWidth = scWidth;
	//viewHeight = scHeight - infoBarHeight;
	
	c = document.getElementById("playArea");
	ctx = c.getContext("2d");
	

	c.onmousedown = function(e){
		//alert("pressed mouse");
		//console.log(e);
		lastE = e;
		if(e.which != 1)return;
		mousePressed = true;
		mouseX = e.offsetX; //screen = screen
		mouseY = e.offsetY; //screen = screen
		if(mouseY < scHeight - infoBarHeight){
			dragStartX = getWorldX(mouseX); //world = getWorld(screen)
			dragStartY = getWorldY(mouseY); //world = getWorld(screen)
			/*if(!panning){
				draggedPlanet = new Body(newPlanetMass, dragStartX, dragStartY);
				dragging = true;
			}*/
		}
	};

	c.onmousemove = function(e){
		//mousePos(e);
		//console.log(e);
		mouseX = e.offsetX; //screen = screen
		mouseY = e.offsetY; //screen = screen
		if(mousePressed && panning){
			scnOffset.x += ((mouseX - lastE.offsetX) / scale); //screen = screen - getScreen(world)
			scnOffset.y += ((mouseY - lastE.offsetY) / scale); //screen = screen - getScreen(world)
		}
		/*else if(dragging){
			draggedPlanet.x = getWorldX(e.offsetX); //world = getWorld(screen)
			draggedPlanet.y = getWorldY(e.offsetY); //world = getWorld(screen)
		}*/
		lastE = e;
	};

	c.onmouseup = function(e){
		mousePressed = false;
		/*if(dragging){
			dragging = false;
			dragEndX = getWorldX(e.offsetX); //world = getWorld(screen)
			dragEndY = getWorldY(e.offsetY); //world = getWorld(screen)
			var pullLength = dist(dragStartX, dragStartY, dragEndX, dragEndY);
			var releaseMotion = new Vector((dragStartX - dragEndX)/12, (dragStartY - dragEndY)/12);
			bodies.push(new Body(draggedPlanet.mass, getWorldX(e.offsetX), getWorldY(e.offsetY), releaseMotion));
			
			//if recording
			if(isRecording){
				//add new planet event to recording
				recording.push(new Event('bookmark', gameTime, bodies));
			}
		}*/
	};
	redraw();
	
	function redraw(){
		//copy in some global variables
		var _viewHeight = viewHeight, _viewWidth = viewWidth;
		var bgColor = "#000000";
		var bodyColor = "#888888";
		var offScreenColor = "#EA4B00";
		var trailColor = "#555555";
		var offScreenOutline = "#555555";
		var _showTrails = showTrails;
		var _scale = scale;
		var motionColor = "#CC4444";
		var _showMotionVector = showMotionVector;
		
		//clear the screen
		ctx.fillStyle = bgColor;
		ctx.fillRect(0,0,scWidth,scHeight);
		
		var TWOPI = Math.PI * 2;
		
		if(!paused){
			

			updateBodiesAcc();
			updateBodiesPos();
			resolveCollisions();
			
			//look for all events with this time and handle the events
			while(recording.length > 0 && recording[0].time == gameTime){
				var nextEvent = recording.shift();
				switch(nextEvent.type){
					case "bookmark":
						//replace the bodies array
						bodies = [];
						for(i = 0; i < nextEvent.data.length; i++){
							bodies.push(new Body(nextEvent.data[i]));
						}
						break;
					case "newPlanet":
						//add the planet to the bodies array
						bodies.push(new Body(nextEvent.data));
						break;
					case "zoom":
						if(playExtras){
							//set the scale
							scale = nextEvent.data;
						}
						break;
					case "pan":
						if(playExtras){
							//set the screen offset
							scnOffset = nextEvent.data;
						}
						break;
					case "motion":
						//set the motion vector booleans
						showMotionVector = _showMotionVector = nextEvent.data;
						break;
					case "trails":
						//set the trails booleans
						showTrails = _showTrails = nextEvent.data;
						break;
					case "stop":
						//pause the simulation
						paused = true;
						recordEnded = true;
						break;
				}
			}
			gameTime++;
		}
		
		var i = bodies.length;
		while(i--){
			var I = bodies[i];
			var planetRad = (I.width/2)*_scale;
			if(_showTrails){
				//draw the planet's trail
				ctx.strokeStyle = trailColor;
				ctx.beginPath();
				for(c = 0, cLen = I.trail.length-1; c < cLen; c++){
					ctx.moveTo(getScX(I.trail[c].x), getScY(I.trail[c].y));
					ctx.lineTo(getScX(I.trail[c+1].x), getScY(I.trail[c+1].y));
				}				
				ctx.stroke();
			}
			var nX = I.getScX();
			var nY = I.getScY();
			//if the planet is completely off the screen
			if(nX - planetRad > _viewWidth || nX + planetRad < 0 || nY - planetRad > _viewHeight || nY + planetRad < 0){
				//to-do: don't draw a circle in the corner if there's already one there
				
				//var nX = I.getScX();
				if(nX > _viewWidth){
					nX = _viewWidth - 5;
				}
				else if(nX < 0){
					nX = 5;
				}
				
				if(nY > _viewHeight){
					nY = _viewHeight - 5;
				}
				else if(nY < 0){
					nY = 5;
				}
				//draw red circle
				ctx.beginPath();
				ctx.arc(nX, nY, 2.5, 0, TWOPI);
				ctx.closePath();
				ctx.fillStyle = offScreenColor;
				ctx.fill();
				ctx.strokeStyle = offScreenOutline;
				ctx.stroke();
			}
			else{
				//draw planet
				ctx.beginPath();
				ctx.arc(nX, nY, (I.width/2)*_scale, 0, TWOPI);
				ctx.closePath();
				ctx.fillStyle = I.bodyColor;
				ctx.fill();
				//Draw a box around the planet
				/*
				var radius = (I.width/2)*_scale;
				ctx.beginPath();
				ctx.rect(nX - radius - 5, nY - radius - 5, radius*2 + 10, radius*2 + 10);
				ctx.stroke();
				*/
				
				//draw center
				/*ctx.beginPath();
				ctx.arc(nX, nY, 1, 0, TWOPI);
				ctx.closePath();
				ctx.fillStyle = offScreenColor;
				ctx.fill();*/
			}
			if(_showMotionVector){
				//draw a line from the center of a planet showing the direction and speed it's travelling
				ctx.strokeStyle = motionColor;
				ctx.beginPath();
				ctx.moveTo(I.getScX(), I.getScY());
				ctx.lineTo(I.motion.x * _scale * 12 + I.getScX(), I.motion.y * _scale * 12 + I.getScY());
				ctx.stroke();
			}
		}
		//draw a semi-transparent planet where the cursor is
		/*if(!panning){
			var radius = newPlanetRadius * _scale;
			
			ctx.beginPath();
			ctx.arc(mouseX, mouseY, radius, 0, TWOPI);
			ctx.fillStyle = bodyColor;
			ctx.fill();
			
			ctx.lineStyle = "#FF0000";
			ctx.beginPath();
			ctx.rect(mouseX - radius - 5, mouseY - radius - 5, radius*2 + 10, radius*2 + 10);
			ctx.stroke();
		}*/
		
		//draw the planet you're about to launch
		/*if(mousePressed && dragging){
			ctx.fillStyle = bodyColor;
			ctx.lineStyle = trailColor;
			//draw a line from drag start to current mouse position
			ctx.beginPath();
			ctx.moveTo(getScX(dragStartX), getScY(dragStartY));
			ctx.lineTo(mouseX, mouseY);
			ctx.stroke();
			//draw a circle at the mouse position
			ctx.beginPath();
			ctx.arc(mouseX, mouseY, (draggedPlanet.width/2)*_scale, 0, TWOPI);
			ctx.fillStyle = bodyColor;
			ctx.fill();
		}*/
		drawInfo();
		setTimeout(redraw, 1000/60);
		
	}
	//seedScreen();
};

function mousePos(e){
	var thisx = e.offsetX;
	var thisy = e.offsetY;
	
	/*document.getElementById('screenCoord').innerHTML = "(" + thisx + ", " + thisy + ")";
	document.getElementById('worldCoord').innerHTML = "(" + getWorldX(thisx) + ", " + getWorldY(thisy) + ")";
	document.getElementById('offset').innerHTML = "(" + scnOffset.x + ", " + scnOffset.y + ")";*/
}


function seedScreen(){
	clearScreen();
	scnOffset = new Vector();
	
	//M, X, Y, new Vector(X, Y)
	/*//sun
	bodies.push(new Body(1.9891E30, 0, 0, new Vector(0, 0)));
	//mercury
	bodies.push(new Body(3.3022E23, 57910000, 0, new Vector(0, 47.87)));
	*/
	
	
	for(i = 0, sbc = startBodyCount; i < sbc; i++){
		bodies.push(new Body());
	}
	//avoid overlapping planets shooting off
	resolveCollisions();
	
	//if recording
	if(isRecording){
		//add seed screen event to recording
		recording.push(new Event('bookmark', gameTime, bodies));
	}
}

function togglePause(){
	paused = !paused;
	
	document.getElementById("pauseButton").innerHTML = (paused)? "Unpause" : "Pause";
}

function setPause(_p){
	paused = _p;
	document.getElementById("pauseButton").innerHTML = (paused)? "Unpause" : "Pause";
}

/*function togglePan(){
	panning = !panning;
	
	document.getElementById("panToggleButton").innerHTML = (panning)? "Launch Planet" : "Move camera";
	document.getElementById('messageBox').innerHTML = (panning)? "Click and drag to move the camera" : "Click and drag to launch a planet";
	document.getElementById('playArea').style.cursor = (panning)? "move" : "none";
}*/

function toggleTrails(){
	showTrails = !showTrails;

	document.getElementById("toggleTrails").innerHTML = (showTrails)? "Hide Trails" : "Show Trails";
	
	//if recording
	if(isRecording){
		//add trail toggle event to recording
		recording.push(new Event('trails', gameTime, showTrails));
	}
}

function toggleMotionVector(){
	showMotionVector = !showMotionVector;
	
	document.getElementById("toggleMotionVector").innerHTML = (showMotionVector)? "Hide Direction" : "Show Direction";
	
	//if recording
	if(isRecording){
		//add motion vector event to recording
		recording.push(new Event('motion', gameTime, showMotionVector));
	}
}

/*function clearScreen(){
	bodies = [];
	scnOffset = new Vector();
	
	//if recording
	if(isRecording){
		//add clear event to recording
		recording.push(new Event('bookmark', gameTime, bodies));
	}
}*/

/*function incLaunchSize(){
	if(newPlanetMass < 1024000){
		newPlanetMass *= 2;
		newPlanetRadius = Math.pow((Math.abs(newPlanetMass) * 3 / (4 * Math.PI)), 0.3333);
		document.getElementById('launchSize').innerHTML = newPlanetMass;
	}
}*/

/*function decLaunchSize(){
	if(newPlanetMass > 25){
		newPlanetMass /= 2;
		newPlanetRadius = Math.pow((Math.abs(newPlanetMass) * 3 / (4 * Math.PI)), 0.3333);
		document.getElementById('launchSize').innerHTML = newPlanetMass;
	}
}*/

function incScale(){
	if(scale < 10){
		var oldScale = scale;		
		scale *= 2;
		scnOffset.x -= ((1/scale) * viewWidth) * (oldScale / scale);
		scnOffset.y -= ((1/scale) * viewHeight) * (oldScale / scale);
		
		//if it's not an integer, show the first two decimals
		var percent = ((scale * 100) % 1 === 0)? scale * 100 : (scale * 100).toFixed(2);
		document.getElementById('scale').innerHTML =  percent + '%';		
		//document.getElementById('offset').innerHTML = "(" + scnOffset.x + ", " + scnOffset.y + ")";
		
		//if recording
		/*if(isRecording){
			//add zoom event to recording
			recording.push(new Event('zoom', gameTime, scale));
		}*/
	}
}

function decScale(){
	if(scale > 0.1){		
		scnOffset.x += viewWidth / (2 * scale);
		scnOffset.y += viewHeight / (2 * scale);
		
		scale /= 2;
		
		//if it's not an integer, show the first two decimals
		var percent = ((scale * 100) % 1 === 0)? scale * 100 : (scale * 100).toFixed(2);
		document.getElementById('scale').innerHTML =  percent + '%';
		//document.getElementById('offset').innerHTML = "(" + scnOffset.x + ", " + scnOffset.y + ")";
		
		//if recording
		/*if(isRecording){
			//add zoom event to recording
			recording.push(new Event('zoom', gameTime, scale));
		}*/
	}
}

function drawInfo(){
	document.getElementById('planetCount').innerHTML = bodies.length;
	
	if(recordEnded){
		//inform user of end of recording
		ctx.font = "32px Arial";
		ctx.fillStyle = "#EEEE00";
		ctx.fillText("Movie over", 150, 300);
	}
	//if recording
	/*if(isRecording){
		if(gameTime % 30 == 0){
			showRecordingText = !showRecordingText;
		}
	}
	else{
		showRecordingText = false;
	}
	if(showRecordingText){
		//draw the word 'RECORDING' on the top-left corner of the screen
		ctx.font = "24px Arial";
		ctx.fillStyle = "#EEEE00";
		ctx.fillText("Recording", 15, 30);
	}*/
}

//keyPressed function

//mousePressed function

//mouseDragged function

//mouseReleased function

function resolveCollisions(){
	for(i = 0; i < bodies.length; i++){
		var I = bodies[i];
		for(c = 0; c < bodies.length; c++){
			if(c == i)continue;
			//if(bodies[i].mass == -1 || bodies[c].mass == -1)continue;
			
			var C = bodies[c];
			var distance = theDistance(I, C);
			if(distance >= I.width/2 + C.width/2)continue;
			
			var newMass = I.mass + C.mass;
			
			var newx = ((I.x * (I.mass / newMass)) + (C.x * (C.mass / newMass)));
			var newy = ((I.y * (I.mass / newMass)) + (C.y * (C.mass / newMass)));
			
			var newVx = ((I.motion.x * (I.mass / newMass)) + (C.motion.x * (C.mass / newMass)));
			var newVy = ((I.motion.y * (I.mass / newMass)) + (C.motion.y * (C.mass / newMass)));
			
			bodies.push(new Body(newMass, newx, newy, new Vector(newVx, newVy)));
			
			//remove bodies[i]
			var idx = bodies.indexOf(I);
			if(idx != -1)bodies.splice(idx, 1);
			//remove bodies[c]
			idx = bodies.indexOf(C);
			if(idx != -1)bodies.splice(idx, 1);
			break;
		}
	}
}

function updateBodiesAcc(){
	//copy in global variables
	var _G = G;
	for(i = 0, len = bodies.length; i < len; i++){
		var I = bodies[i];
		
		for(c = 0, cLen = bodies.length; c < cLen; c++){
			if(c != i){
				var C = bodies[c];
				var distan = theDistance(I, C);
				
				var vx = C.x - I.x;
				var vy = C.y - I.y;
				var magnitude = Math.sqrt(Math.pow(vx, 2) + Math.pow(vy, 2))
				var ux = vx / magnitude;
				var uy = vy / magnitude;
				var acc = (_G * C.mass) / Math.pow(distan, 2);
				
				bodies[i].motion.x += ux * acc;
				bodies[i].motion.y += uy * acc;
			}
		}
	}
}

function updateBodiesPos(){
	var i = bodies.length;
	while(i--){
		bodies[i].translate();
	}
}

//------------------------------
//BODY CLASS
function Body(/* nothing | Saved Body | M, X, Y | M, X, Y, init */){
	if(arguments.length == 0){
		this.mass = random(25, 150);
		this.x = random(0, viewWidth);
		this.y = random(0, viewHeight);
		//this.motion = new Vector(random(1)-0.5, random(1)-0.5);
		this.motion = new Vector();
	}
	else if(arguments.length == 1){
		this.mass = arguments[0].mass;
		this.x = arguments[0].x;
		this.y = arguments[0].y;
		this.motion = new Vector(arguments[0].motion.x, arguments[0].motion.y);
	}
	else if(arguments.length == 3){
		this.mass = arguments[0];
		this.x = arguments[1];
		this.y = arguments[2];
		this.motion = new Vector();
	}
	else if(arguments.length == 4){
		this.mass = arguments[0];
		this.x = arguments[1];
		this.y = arguments[2];
		this.motion = arguments[3];
	}
	this.trail = [];
	this.width = 2 * ( Math.pow((Math.abs(this.mass) * 3 / (4 * Math.PI)), 0.3333) );
	
	this.bodyColor = (this.mass >= 0)? "#BBBBBB" : "#AC1111";
}

Body.prototype.translate = function(){
	if(showTrails){
			this.trail.push(new Vector(this.x, this.y));
			if(this.trail.length > trailLength){
				this.trail.shift();
			}
		}
		else{
			this.trail = [];
		}
		this.x += this.motion.x;
		this.y += this.motion.y;
}

Body.prototype.getScX = function(){
	return (this.x + scnOffset.x) * scale;
}

Body.prototype.getScY = function(){
	return (this.y + scnOffset.y) * scale;
}
//END BODY CLASS
//------------------------------

//------------------------------
//VECTOR CLASS
function Vector(/* nothing | X, Y*/){
	if(arguments.length == 0){
		this.x = 0;
		this.y = 0;
	}
	else if(arguments.length == 2){
		this.x = arguments[0];
		this.y = arguments[1];
	}	
}
//END VECTOR
//-------------------------------

function getScX(x){
	return (x + scnOffset.x) * scale;
}
function getScY(y){
	return (y + scnOffset.y) * scale;
}

function getWorldX(x){
	return (x / scale) - scnOffset.x;
}
function getWorldY(y){
	return (y / scale) - scnOffset.y;
}

function theDistance(a, b){
	return Math.sqrt(Math.pow(a.x - b.x, 2) + Math.pow(a.y - b.y, 2));
}

function random(min, max){
	if(arguments.length == 1){
		return(Math.random()*arguments[0])+1;
	}
	return(Math.random()*(max-min))+(min + 1);
}

function dist(x1, y1, x2, y2){
	return Math.sqrt(Math.pow(x2 - x1, 2) + Math.pow(y2 - y1, 2));
}

//VIDEO PLAYBACK FUNCTIONS

function restartRecording(){
	//reset the gameTime to 0
	gameTime = 0;
	//clear the bodies array
	bodies = [];
	recording = JSON.parse(recordingjson);
	paused = false;
}

function toggleExtras(){
	playExtras = !playExtras;
	document.getElementById("toggleExtras").innerHTML = (playExtras)? "Disable zoom and pan events" : "Enable zoom and pan events";
}

//VIDEO RECORDING FUNCTIONS

function startRecording(){
	alert("started the recording");
	//create a variable in local storage
	//set the timestamp variable to 0
	gameTime = 0;
	//set the recording boolean to TRUE
	isRecording = true;
	recording = [];
	recording.push(new Event('bookmark', gameTime, bodies));
}

function stopRecording(){
	alert("stopped the recording");
	if(isRecording){
		recording.push(new Event('stop', gameTime, true));
	}
	//save the recording to local storage
	//set the timestamp variable to 0
	gameTime = 0;
	//set the recording boolean to FALSE
	isRecording = false;
	
	//let the user review and save the recording
}

function addRecordBookmark(){
	alert("added bookmark");
	//save the current state in an event
	recording.push(new Event('bookmark', gameTime, bodies));
}

function Event(type, time, data){
	//TYPES: bookmark (includes initial state, reset, and clear), stop, zoom, pan, show motion vector, show trails, and new planet
	this.type = type;
	//game timestamp of the event
	this.time = time;
	//Data will be different based on which event type:
		//bookmark: an array of Body objects
		//stop: boolean value 'true'
		//zoom: new zoom ratio
		//pan: new screen offset
		//motion: boolean
		//trails: boolean
		//new planet: a Body
	this.data = data;
}
